module dactor.socket;

private import dactor.eventlet;
private import core.sys.posix.sys.socket;
private import core.stdc.errno;
private import std.socket;

version(Posix) {
    enum : uint {
        MSG_DONTWAIT = 0x40
    }
}

class Socket {
    private int handle;

    public this(int h) {
        handle = h;
    }

    /*
    public int recvn(ref char[] buffer, int timeout=-1) {

    }
    */

    public int recv(ref char[] buffer, int timeout=-1) {
        while (true) {
            // Optimize event register
            int n = .recv(handle, buffer.ptr, buffer.length, MSG_DONTWAIT);
            if (n >= 0)
                return n;
            if (getErrno() == EINTR)
                continue;
            if (getErrno() == EAGAIN)
                break;
            return n;
        }
        
        scope auto e = new Event(handle, Event.READ, timeout);
        if (Event.TIMEOUT == e.wait())
            return -1;

        while (true) {
            int n = .recv(handle, buffer.ptr, buffer.length, MSG_DONTWAIT);
            if (n >= 0)
                return n;
            if (getErrno() == EINTR)
                continue;
            return -1;
        }
    }

    public int send(in char[] buffer, int timeout=-1) {

        while (true) {
            // Optimize event register
            int n = .send(handle, buffer.ptr, buffer.length, MSG_DONTWAIT);
            if (n >= 0)
                return n;
            if (getErrno() == EINTR)
                continue;
            if (getErrno() == EAGAIN)
                break;
            return n;
        }

        scope auto e = new Event(handle, Event.WRITE, timeout);

        if (Event.TIMEOUT == e.wait())
            return -1;

        while (true) {
            int n = .send(handle, buffer.ptr, buffer.length, MSG_DONTWAIT);
            if (n >= 0)
                return n;
            if (getErrno() == EINTR)
                continue;
            return -1;
        }
    }
}

